from common_data import *
from permission import *
from twisted.web import xmlrpc
from twisted.python import log
from sqlobject import dberrors

class XMLRPC_PartyResource( xmlrpc.XMLRPC ):
    _permissions = {
        'addAdminToParty':          PERMISSION_REQUIREMENT_PARTY_ADMIN,
        'addParty':                 PERMISSION_REQUIREMENT_GLOBAL_ADMIN,
        'addUserToParty':           PERMISSION_REQUIREMENT_PARTY_ADMIN,
        'delAdminFromParty':        PERMISSION_REQUIREMENT_PARTY_ADMIN,
        'delParty':                 PERMISSION_REQUIREMENT_GLOBAL_ADMIN,
        'delUserFromParty':         PERMISSION_REQUIREMENT_PARTY_ADMIN,
        'getPartyByID':             PERMISSION_REQUIREMENT_GLOBAL_USER,
        'getPartyByName':           PERMISSION_REQUIREMENT_GLOBAL_USER,
        'listParties':              PERMISSION_REQUIREMENT_GLOBAL_USER,
    }
    
    def __init__(self):
        """load config"""
        
        log.msg( 'Party resource init' )
        xmlrpc.XMLRPC.__init__(self)
        
    def xmlrpc_listParties(self):
        """return list of user parties"""
        
        try:
            parties = Party.select( orderBy=Party.q.id )
        except:
            log.err()
            return False
        
        return list( ( party.id, party.name ) for party in parties )
    
    xmlrpc_listParties.signature = [['array']]
    
    def xmlrpc_getPartyByName(self, party_name ):
        """get party by party_name"""
        
        if not str( party_name ):
            raise xmlrpc.Fault( 123, 'invalid argument' )
        
        try:
            party = Party.selectBy( name = str( party_name ) ).getOne()
        except SQLObjectNotFound:
            raise xmlrpc.Fault( 123, 'party not found' )
        except:
            log.err( 'could not retrieve party. party_name: %s' % str( party_name ) )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve party' )
                    
        return self.partyResultToDict( party )
    
    xmlrpc_getPartyByName.signature = [['array','string']]
    
    def xmlrpc_getPartyByID(self, party_id ):
        if not int( party_id ):
            raise xmlrpc.Fault( 123, 'invalid argument' )
        
        party = getPartyById( party_id )
                    
        return self.partyResultToDict( party )
    
    xmlrpc_getPartyByID.signature = [['array','int']]
    
    def xmlrpc_addParty(self, party_name):
        """add new party"""
        
        if not str( party_name ):
            log.err('party_name not submitted')
            raise xmlrpc.Fault( 123, 'party_name not submitted' )
        
        try:
            party = Party( name = str( party_name ) )
        except dberrors.DuplicateEntryError:
            log.err( 'attempt to create duplicate party %s' % str( party_name ) )
            raise xmlrpc.Fault( 123, 'party_name already exists' )
        except:
            log.err()
            raise xmlrpc.Fault( 123, 'unable to create new party' )

        return party.id
    
    xmlrpc_addParty.signature = [['int','string']]
    
    def xmlrpc_delParty(self, party_id):
        """delete existing party"""
        
        if not int( party_id ):
            log( 'party_id not submitted' )
            raise xmlrpc.Fault( 123, 'party_id not submitted' )
        
        party = getPartyById( party_id )
        
        party.destroySelf()
        
        return True
    
    xmlrpc_delParty.signature = [['bool','int']]
    
    def xmlrpc_addUserToParty(self, party_id, user_id ):
        """add user to party user list"""
        
        if not int( party_id ):
            log.err('party_id not submitted')
            raise xmlrpc.Fault( 123, 'party_id not submitted')
        
        if not int( user_id ):
            log.err('user_id not submitted')
            raise xmlrpc.Fault( 123, 'user_id not submitted')
        
        party = getPartyById( party_id )
        user = getUserById( user_id )
        
        try:
            party.addUser( user )
        except:
            log.err( 'could not add user to party; party_id: %d, user_id: %d' % ( party_id, user_id ) )
            raise xmlrpc.Fault( 123, 'could not add user to party' )
        
        return True
    
    xmlrpc_addUserToParty.signature = [['bool','int','int']]
        
    def xmlrpc_delUserFromParty(self, party_id, user_id ):
        """delete user from party user list"""

        if not int( party_id ):
            log.err('party_id not submitted')
            raise xmlrpc.Fault( 123, 'party_id not submitted')
        
        if not int( user_id ):
            log.err('user_id not submitted')
            raise xmlrpc.Fault( 123, 'user_id not submitted')
        
        party = getPartyById( party_id )
        user = getUserById( user_id )
        
        try:
            party.removeUser( user )
        except:
            log.err( 'could not remove user ( %d ) from party ( %d )' % ( user_id, party_id ) )
            raise xmlrpc.Fault( 123, 'could not remove user from party' )
        
        return True
    
    xmlrpc_delUserFromParty.signature = [['bool','int','int']]
    
    def xmlrpc_addAdminToParty(self, party_id, user_id ):
        """add user to party admin list"""
        
        if not int( party_id ):
            log.err('party_id not submitted')
            raise xmlrpc.Fault( 123, 'party_id not submitted')
        
        if not int( user_id ):
            log.err('user_id not submitted')
            raise xmlrpc.Fault( 123, 'user_id not submitted')
        
        party = getPartyById( party_id )
        user = getUserById( user_id )
        
        try:
            party.addAdmin( user )
        except:
            log.err( 'could not add admin to party; party_id: %d, user_id: %d' % ( party_id, user_id ) )
            raise xmlrpc.Fault( 123, 'could not add admin to party' )
        
        return True
    
    xmlrpc_addAdminToParty.signature = [['bool','int','int']]
    
    def xmlrpc_delAdminFromParty(self, party_id, user_id ):
        """delete user from party admin list"""
 
        if not int( party_id ):
            log.err('party_id not submitted')
            raise xmlrpc.Fault( 123, 'party_id not submitted')
        
        if not int( user_id ):
            log.err('user_id not submitted')
            raise xmlrpc.Fault( 123, 'user_id not submitted')
        
        party = getPartyById( party_id )
        user = getUserById( user_id )
        
        try:
            party.removeAdmin( user )
        except:
            log.err( 'could not remove admin ( %d ) from party ( %d )' % ( user_id, party_id ) )
            raise xmlrpc.Fault( 123, 'could not remove admin from party' )
        
        return True
    
    xmlrpc_delAdminFromParty.signature = [['bool','int','int']]

    def partyResultToDict(self, party ):
            result = dict()
            result['id'] = party.id
            result['name'] = party.name
            result['users'] = list( user.id for user in party.users )
            result['admins'] = list( admin.id for admin in party.admins )
            result['active_checkouts'] = list( checkout.id for checkout in party.active_checkouts )

            result['creation_time'] = xmlrpc.DateTime( party.creation_time ).value
            result['modified_time'] = xmlrpc.DateTime( party.modified_time ).value
            
            return result